home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / StackCall.a < prev    next >
Text File  |  1996-10-20  |  4KB  |  183 lines

  1. **
  2. **    StackCall.a
  3. **
  4. **    Stack swap & stack size check routines for SAS/C
  5. **    using the small data model
  6. **
  7. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  8. **        All Rights Reserved
  9. **
  10.  
  11.     include    "exec/types.i"
  12.     include    "exec/tasks.i"
  13.     include    "exec/memory.i"
  14.     include    "exec/execbase.i"
  15.  
  16.     include    "dos/dos.i"
  17.     include    "dos/dosextens.i"
  18.  
  19. *----------------------------------------------------------------------
  20.  
  21. CALL    macro
  22.     xref    LVO\1
  23.     jsr    LVO\1(a6)
  24.     endm
  25.  
  26. *----------------------------------------------------------------------
  27.  
  28. ARG_SUCCESS    equ    4+5*4
  29. ARG_STACKSIZE    equ    ARG_SUCCESS+4
  30. ARG_ARGCOUNT    equ    ARG_STACKSIZE+4
  31. ARG_ROUTINE    equ    ARG_ARGCOUNT+4
  32. ARG_ARGS    equ    ARG_ROUTINE+4
  33.  
  34. TRUE        equ    1
  35. FALSE        equ    0
  36.  
  37. *----------------------------------------------------------------------
  38.  
  39.     section    text,code
  40.  
  41. *----------------------------------------------------------------------
  42.  
  43.     xdef    StackCall
  44.  
  45.     ;    LONG __stdargs StackCall(    LONG *Success,
  46.     ;                    LONG StackSize,
  47.     ;                    LONG ArgCount,
  48.     ;                    LONG (* __stdargs Function)(...),
  49.     ;                    ...);
  50.     ;
  51.     ;    Calls a function with parameters on a newly-allocated
  52.     ;    stack. Caution: assumes all arguments are 32 bits wide.
  53.  
  54. StackCall:
  55.  
  56.     movem.l    d2/d3/a2/a3/a6,-(sp)        ; Save registers
  57.  
  58.     move.l    ARG_STACKSIZE(sp),d0        ; Get desired stack size
  59.     add.l    #15+StackSwapStruct_SIZEOF,d0    ; Round to next...
  60.     and.l    #-16,d0                ; ...quad long word
  61.     move.l    d0,d2                ; Save it for later
  62.     move.l    #MEMF_PUBLIC,d1            ; Well?
  63.     move.l    SysBase(a4),a6            ; Get SysBase
  64.  
  65.     CALL    AllocMem            ; Allocate the memory
  66.     tst.l    d0                ; Success?
  67.     beq.b    1$                ; Exit if not
  68.  
  69.     move.l    d0,a2                ; Remember base adress
  70.  
  71.     add.l    #StackSwapStruct_SIZEOF,d0    ; Skip the header
  72.     move.l    d0,stk_Lower(a2)        ; Store the stack lower bound
  73.  
  74.     move.l    a2,a3                ; Get the base address
  75.     add.l    d2,a3                ; Add the allocation size
  76.     move.l    a3,stk_Upper(a2)        ; Store the stack upper bound
  77.  
  78.     move.l    ARG_ARGCOUNT(sp),d0        ; Get the number of arguments
  79.     beq.b    3$                ; Skip if none
  80.  
  81.     moveq    #4,d1                ; One long word per argument
  82.     mulu    d0,d1                ; Nasty
  83.     ext.l    d1                ; Forget the upper word
  84.     addq.l    #4,d1                ; One for predecrement
  85.     sub.l    d1,a3                ; Pull it down
  86.  
  87.     subq.l    #1,d0                ; Subtract one for DBRA
  88.     lea.l    ARG_ARGS(sp),a0            ; Get the source argument list
  89.     move.l    a3,a1                ; Get the destination argument list
  90.  
  91. 2$    move.l    (a0)+,(a1)+            ; Copy the parameters
  92.     dbra    d0,2$                ; Loop until all is copied
  93.  
  94. 3$    move.l    a3,stk_Pointer(a2)        ; Store the new stack pointer
  95.  
  96.     move.l    ARG_ROUTINE(sp),a3        ; Get address of the routine to call
  97.  
  98.     move.l    a2,a0                ; Swap the stack
  99.     CALL    StackSwap
  100.  
  101.     jsr    (a3)                ; Call the routine
  102.     move.l    d0,d3                ; Save the result
  103.  
  104.     move.l    a2,a0                ; Swap the stack
  105.     CALL    StackSwap
  106.  
  107.     move.l    a2,a1                ; Get the base address
  108.     move.l    d2,d0                ; Get the allocation length
  109.     CALL    FreeMem                ; Free the memory
  110.  
  111.     move.l    ARG_SUCCESS(sp),a0        ; Flag as success
  112.     move.l    #TRUE,(a0)
  113.  
  114.     move.l    d3,d0                ; Return the result
  115.  
  116.     movem.l    (sp)+,d2/d3/a2/a3/a6        ; Restore registers
  117.     rts
  118.  
  119. 1$    move.l    ARG_SUCCESS(sp),a0        ; Flag as failure
  120.     move.l    #FALSE,(a0)
  121.  
  122.     movem.l    (sp)+,d2/d3/a2/a3/a6        ; Restore registers
  123.     rts
  124.  
  125. *----------------------------------------------------------------------
  126.  
  127.     xdef    @StackSize
  128.     xdef    StackSize
  129.  
  130.     ;    LONG StackSize(struct Task *Task);
  131.     ;
  132.     ;    Determines the amount of stack still available to a task.
  133.     ;    Pass in NULL as the task address to return the amount
  134.     ;    of stack available to the calling task.
  135.  
  136. StackSize:
  137.     move.l    4(sp),a0            ; Get task address
  138.  
  139. @StackSize:
  140.     move.l    a6,-(sp)            ; Save registers
  141.  
  142.     move.l    SysBase(a4),a6            ; Get SysBase
  143.  
  144.     move.l    a0,d0                ; Valid task address?
  145.     beq.b    4$
  146.  
  147.     move.l    TC_SPREG(a0),d0            ; Remember stack pointer
  148.     bra.b    3$
  149.  
  150. 4$    move.l    a0,a1
  151.     CALL    FindTask            ; Who am I?
  152.     move.l    d0,a0                ; That's me
  153.     move.l    sp,d0                ; Remember stack pointer
  154.  
  155. 3$    cmp.b    #NT_PROCESS,LN_TYPE(a0)        ; Is this a process?
  156.     bne.b    1$
  157.  
  158.     tst.l    pr_CLI(a0)            ; Is it running as a CLI process?
  159.     beq.b    1$
  160.  
  161.     move.l    pr_ReturnAddr(a0),d1        ; Get upper bound
  162.     addq.l    #4,d1
  163.     move.l    pr_ReturnAddr(a0),a0
  164.     sub.l    (a0),d1                ; Subtract total stack size
  165.  
  166.     bra.b    2$
  167.  
  168. 1$    move.l    TC_SPLOWER(a0),d1        ; Get lower bound
  169.  
  170. 2$    sub.l    d1,d0                ; Subtract from stack pointer
  171.  
  172.     move.l    (sp)+,a6            ; Restore registers
  173.  
  174.     rts
  175.  
  176. *----------------------------------------------------------------------
  177.  
  178.     section    __MERGED,data
  179.  
  180.     xref    SysBase
  181.  
  182.     end
  183.